home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / emac16as.arc / REDISP.ASM < prev    next >
Assembly Source File  |  1990-04-01  |  42KB  |  1,806 lines

  1. ;History:1712,1
  2. ;Thu Feb 22 15:43:22 1990 output the blanks for a tab specially.
  3. ;Fri Feb 02 07:20:33 1990 don't forget the "more" symbol if we have trailing whitespace.
  4. ;Wed Nov 15 23:51:43 1989 use num_screen_cols-1 columns.
  5. ;Tue Nov 14 22:48:37 1989 add scrollbar code.
  6. ;Fri Jun 02 00:36:53 1989 gotoxy should position the cursor also.
  7. ;Sun Mar 26 20:45:02 1989 optimize a little code in store_current_window.
  8. ;06-26-88 23:53:50 in chrout, CR was changing the line w/o setting TRASHED.
  9. ;05-17-88 22:39:59 Make CGA scroll if only one line [kdb]
  10. ;05-17-88 22:09:22 Force redraw for CGA [kdb]
  11. ;05-17-88 19:39:15 Remove reference to scrwait [kdb]
  12. ;04-01-88 22:42:23 add tab_size to allow for varying tab sizes.
  13. ;03-26-88 14:37:44 on 40 column screens, fix horizontal scrolling (40 / 2) % 8 != 0
  14. ;11-16-87 23:18:13 remove memsize
  15. ;11-15-87 22:50:18 make w1_windseg, and w2_windseg for buffers.asm's sake.
  16. ;09-09-87 00:48:00 compute the middle of the screen, rather than assuming column 40.
  17. ;07-13-87 23:08:49 remove xyputch
  18. ;07-13-87 22:58:51 move the call to paint_screen into init_screen.
  19. ;07-07-87 22:37:35 also check for eof in trailing blanks code
  20. ;07-07-87 22:12:44 check for bottom correctly in redraw_line
  21. ;07-07-87 22:10:54 in redraw_line, move the check where we need it.
  22. ;07-06-87 06:52:39 use botbot to check for eof, not LINENEW
  23.     .xlist
  24.  
  25. HT    equ    09h
  26. LF    equ    0ah
  27. CR    equ    0dh
  28. LINENEW    equ    CR+LF*256    ;the way a newline is stored in memory.
  29.  
  30. TRAIL_BLANK    equ    4dh
  31. TRAIL_TAB    equ    4eh
  32. MORE_CHAR    equ    52h
  33. NEWLINE_CHAR    equ    54h
  34. UP_CHAR        equ    55h
  35. DOWN_CHAR    equ    56h
  36. TAB_BLANK    equ    57h
  37.  
  38. bufseg    segment    byte public
  39.  
  40.     extrn    toptop: word
  41.     extrn    topbot: word
  42.     extrn    bottop: word
  43.     extrn    botbot: word
  44.  
  45.     extrn    linecount: word
  46.     extrn    linesbefore: word
  47.  
  48. bufseg    ends
  49.  
  50. data    segment    byte public
  51.  
  52.   if 1
  53.     public    w1, w2, this_point, this_row, other_row, topbotpercent
  54.     public    botpercent, toppercent, firstlimit, lastlimit, overwrite_row
  55.     public    overwrite_col, screen_column, window, inversed, inverse_mark
  56.     public    showblanks
  57.   endif
  58.  
  59. ;pointrow contains the row that the cursor is currently on, relative to the
  60. ;  screen boundaries.  Pointrow may be negative if the point is above the screen,
  61. ;  or it may be larger than max_screen_line if the point is below the screen.
  62.  
  63. wind_struc    struc
  64. windseg        dw    ?
  65. pointrow    dw    ?
  66. firstline    db    ?
  67. lastline    db    ?
  68. firstpossible    db    ?
  69. lastpossible    db    ?
  70. firstcolumn    dw    ?
  71. wind_struc    ends
  72.  
  73. w1    wind_struc<>
  74.  
  75. w2    wind_struc<>
  76.  
  77.     public    w1_windseg, w2_windseg
  78. w1_windseg    equ    w1.windseg
  79. w2_windseg    equ    w2.windseg
  80.  
  81.  
  82. this_point    dw    ?        ;->point in the current file.
  83. this_row    dw    ?        ;row of point on screen.
  84. other_row    dw    ?        ;row of point in other window.
  85.  
  86. topbotpercent    label    word
  87. botpercent    db    ?
  88. toppercent    db    ?
  89.  
  90. firstlastlimits    label    word
  91. firstlimit    db    ?
  92. lastlimit    db    ?
  93.  
  94.  
  95.     public    tab_size
  96. tab_size    dw    7        ;mask for tab stops.
  97.  
  98.     public    next_redisp_line
  99. next_redisp_line    dw    0
  100.  
  101.     public    overwrite_flag
  102. overwrite_flag    db    0        ;=0 if not overwriting.
  103.  
  104. overwrite_rowcol    label    word
  105. overwrite_row    db    0
  106. overwrite_col    db    0
  107.  
  108. ;the following externs are in the computer-dependent file
  109.     extrn    max_screen_line: byte
  110.     extrn    num_screen_cols: byte
  111.  
  112. ;the following externs are in 'buffers'
  113.     extrn    textseg: word
  114.  
  115. screen_column    dw    ?
  116.  
  117. ;window contains a list of which lines should be moved where, and which
  118. ;  lines need to be redrawn.  If an entry is positive, then the line which is
  119. ;  currently at x belongs at window[x].  If an entry is TRASHED, it
  120. ;  should be redrawn.
  121. ;inversed contains a list of which lines currently show inverse video.
  122. window        db    128 dup(?)    ;128 is > max_screen_line
  123. inversed    db    128 dup(?)    ;. .
  124. inverse_flag    db    0        ;=0 means no inversing.
  125.     public    inverse_seg        ;used by buffers.asm to adjust.
  126. inverse_seg    dw    0        ;segment of marked buffer.
  127.     public    inversing        ;used by ibm.asm or z100.asm to control
  128. inversing    dw    0        ;  which lines are inversed.
  129.  
  130. inverse_mark    dw    ?        ;pointing to the inverse mark.
  131.  
  132. TRASHED        equ    -1        ;note that TRASHED must be negative.
  133.  
  134. showblanks    db    0
  135.  
  136. data    ends
  137.  
  138. b_struc    struc
  139. b    db    ?
  140. b_struc    ends
  141.  
  142. w_struc    struc
  143. w    dw    ?
  144. w_struc    ends
  145.  
  146. byte_ptr    label    byte
  147.  
  148. code    segment    byte public
  149. ;all the routines in this segment are entered with ds=data, es=data
  150.     assume    cs:code, ds:data, es:data
  151.  
  152.  
  153. ;the following externs are in the computer-dependent file.
  154.     extrn    move_line: near
  155.     extrn    clear_to_eol: near
  156.     extrn    xychrout: near
  157.     extrn    hardware_roll_up: near
  158.     extrn    hardware_roll_down: near
  159.     extrn    position_cursor: near
  160.     extrn    read_ibm_cga: near
  161.  
  162. ;the following externs are in 'memory'
  163.     extrn    compute_cursor$: near
  164.     extrn    set_line$: near
  165.  
  166. ;the following externs are in 'buffers'
  167.     extrn    buffer_number: near
  168.         ;enter with bx=paragraph of buffer.
  169.         ;exit with ax=number of buffer.
  170.     extrn    buffer_allocate: near
  171.     extrn    find_buffer: near
  172.         ;enter with cx=buffer number.
  173.         ;exit with nc, dx set to that buffer if it exists, cy otherwise.
  174.  
  175. ;the following externs are in 'marks'
  176.     extrn    read_mark$: near
  177.     extrn    goto_mark$: near
  178.     extrn    get_split_mark: near
  179.     extrn    get_mark: near
  180.     extrn    split_at_point: near
  181.     extrn    set_mark_si: near
  182.     extrn    set_mark: near
  183.     extrn    stack_marks: near
  184.     extrn    goto_mark: near
  185.  
  186.  
  187.     public    read_current_window
  188. read_current_window:
  189.     mov    ax,1            ;probably window 1.
  190.     cmp    w2.windseg,0        ;no window 2 - must be 1.
  191.     je    read_current_window_1
  192.     mov    bl,w1.firstline
  193.     cmp    bl,w2.firstline
  194.     jb    read_current_window_1
  195.     inc    ax
  196. read_current_window_1:
  197.     ret
  198.  
  199.  
  200.     public    store_current_window
  201. store_current_window:
  202.     cmp    ax,1
  203.     jne    store_current_window_1
  204.     mov    al,w1.firstline
  205.     cmp    al,w2.firstline
  206.     jb    store_current_window_2
  207.     jmp    short store_current_window_3
  208. store_current_window_1:
  209.     cmp    ax,2
  210.     jne    store_current_window_2
  211.     mov    al,w1.firstline
  212.     cmp    al,w2.firstline
  213.     ja    store_current_window_2
  214. store_current_window_3:
  215.     cmp    w2.windseg,0        ;is there a second window?
  216.     je    store_current_window_2    ;no - don't swap.
  217.     call    swap_other_row
  218.     call    swap_windows
  219. store_current_window_2:
  220.     ret
  221.  
  222.  
  223. swap_other_row:
  224.     mov    ax,w1.windseg        ;are we in the other window?
  225.     cmp    ax,w2.windseg
  226.     jne    swap_other_row_1    ;no - no worries.
  227.     push    w1.pointrow        ;remember what other_row will be.
  228.  
  229.     mov    ax,1
  230.     call    stack_marks
  231.     mov    ax,'*'*256+'0'        ;0 := *
  232.     call    set_mark
  233.     mov    ax,'.'*256+'*'        ;* := .
  234.     call    set_mark
  235.     mov    al,'0'            ;. := 0
  236.     call    goto_mark
  237.     mov    ax,0
  238.     call    stack_marks
  239.  
  240.     pop    other_row
  241. swap_other_row_1:
  242.     ret
  243.  
  244.  
  245.     public    read_other_window
  246. read_other_window:
  247.     mov    bx,w2.windseg
  248.     or    bx,bx
  249.     je    read_other_window_1
  250.     call    buffer_number
  251.     ret
  252. read_other_window_1:
  253.     xor    ax,ax
  254.     ret
  255.  
  256.  
  257.     public    store_other_window
  258. store_other_window:
  259. ;enter with ax=buffer segment to show.
  260.     mov    cx,ax            ;do they want one window?
  261.     jcxz    store_other_window_3    ;yes.
  262.     call    find_buffer        ;find the buffer.
  263.     jc    store_other_window_3    ;can't find it - give them one window.
  264.  
  265.     cmp    w2.windseg,0        ;do we have another window to set?
  266.     jne    store_other_window_1    ;yes - just set it.
  267.     push    dx
  268.     call    split_screen
  269.     pop    dx
  270. store_other_window_1:
  271.     cmp    dx,w2.windseg        ;is it already showing?
  272.     je    store_other_window_2    ;yes - they're being silly.
  273.  
  274.     mov    w2.windseg,dx        ;show the buffer here.
  275.  
  276.     cmp    w1.windseg,dx        ;is this buffer also in w1?
  277.     jne    store_other_window_4    ;no - no worries.
  278.  
  279.     mov    ax,w1.pointrow        ;the place that the this window is at
  280.     mov    other_row,ax        ;  becomes the other row.
  281.  
  282.     mov    ax,'.'*256+'*'        ;set the split mark to the point.
  283.     call    set_mark
  284.  
  285. store_other_window_4:
  286.     mov    bl,w2.firstline        ;trash what's there.
  287.     mov    al,w2.lastline
  288.     call    trash_some_lines
  289. store_other_window_2:
  290.     ret
  291.  
  292. store_other_window_3:
  293.     mov    w2.windseg,0
  294.     mov    al,max_screen_line    ;fill the screen with this window.
  295.     mov    w1.lastline,al
  296.     mov    w1.firstline,0
  297.     mov    si,offset w1
  298.     call    set_window_percent
  299.     call    paint_screen
  300.     ret
  301.  
  302.  
  303. split_screen:
  304.     mov    al,max_screen_line
  305.     mov    w2.lastline,al
  306.     sar    al,1
  307.     dec    al
  308.     mov    w1.lastline,al
  309.     add    al,2
  310.     mov    w2.firstline,al
  311. split_recompute:
  312.     mov    si,offset w1
  313.     call    set_window_percent
  314.  
  315.     mov    si,offset w2
  316.     call    set_window_percent
  317.  
  318.     call    paint_screen
  319.  
  320.     ret
  321.  
  322.  
  323.     public    store_firstline
  324. store_firstline:
  325.     cmp    w2.windseg,0        ;do we really have two windows?
  326.     je    store_firstline_1    ;no.
  327.     cmp    w1.firstline,0        ;are we the top window?
  328.     je    store_firstline_1    ;yes - we can't set it.
  329.     cmp    al,2            ;less than 2?
  330.     jb    store_firstline_1    ;yes - would leave no room for the top.
  331.     mov    w1.firstline,al
  332.     sub    al,2
  333.     mov    w2.lastline,al
  334.  
  335.     call    split_recompute
  336. store_firstline_1:
  337.     ret
  338.  
  339.  
  340.     public    store_lastline
  341. store_lastline:
  342.     cmp    w2.windseg,0        ;do we really have two windows?
  343.     je    store_lastline_1    ;no.
  344.     cmp    w1.firstline,0        ;are we the top window?
  345.     jne    store_lastline_1    ;no - we can't set it.
  346.     mov    ah,max_screen_line
  347.     sub    ah,2
  348.     cmp    al,ah            ;at the screen size?
  349.     ja    store_lastline_1    ;yes - would leave no room for the top.
  350.     mov    w1.lastline,al
  351.     add    al,2
  352.     mov    w2.firstline,al
  353.  
  354.     call    split_recompute
  355. store_lastline_1:
  356.     ret
  357.  
  358.  
  359.     public    store_showblanks
  360. store_showblanks:
  361.     cmp    showblanks,al        ;are we changing it?
  362.     mov    showblanks,al        ;store it in any case.
  363.     je    store_showblanks_1    ;if we changed it, paint the window.
  364.     call    paint_window
  365. store_showblanks_1:
  366.     ret
  367.  
  368.  
  369.     public    read_showblanks
  370. read_showblanks:
  371.     mov    al,showblanks
  372.     ret
  373.  
  374.  
  375.     public    read_firstline
  376. read_firstline:
  377.     mov    al,w1.firstline
  378.     ret
  379.  
  380.  
  381.     public    read_lastline
  382. read_lastline:
  383.     mov    al,w1.lastline
  384.     ret
  385.  
  386.  
  387.     public    read_newrow
  388. read_newrow:
  389.     mov    ax,w1.pointrow
  390.     ret
  391.  
  392.  
  393.     public    read_firstcolumn
  394. read_firstcolumn:
  395.     mov    ax,w1.firstcolumn
  396.     ret
  397.  
  398.  
  399.     public    store_firstcolumn
  400. store_firstcolumn:
  401.     and    ax,not 7        ;go to the next leftmost tab stop.
  402.     push    ax
  403.     mov    bl,w1.firstline
  404.     mov    al,w1.lastline
  405.     call    trash_some_lines
  406.     pop    w1.firstcolumn
  407.     ret
  408.  
  409.  
  410.     public    read_top_percent
  411. read_top_percent:
  412.     mov    al,toppercent
  413.     ret
  414.  
  415.  
  416.     public    read_bot_percent
  417. read_bot_percent:
  418.     mov    al,botpercent
  419.     ret
  420.  
  421.  
  422.     public    store_top_percent
  423. store_top_percent:
  424.     mov    toppercent,al
  425.     mov    si,offset w1
  426.     call    set_window_percent
  427.     ret
  428.  
  429.  
  430.     public    store_bot_percent
  431. store_bot_percent:
  432.     mov    botpercent,al
  433.     mov    si,offset w1
  434.     call    set_window_percent
  435.     ret
  436.  
  437.  
  438.     public    read_inverse_mark
  439. read_inverse_mark:
  440.     mov    al,inverse_flag
  441.     ret
  442.  
  443.  
  444.     public    store_inverse_mark
  445. store_inverse_mark:
  446.     mov    inverse_flag,al
  447.     mov    ax,textseg
  448.     mov    inverse_seg,ax
  449.     ret
  450.  
  451.     public    init_screen
  452. init_screen:
  453.     xor    al,al
  454.     mov    w1.firstline,al
  455.     mov    w1.firstpossible,al
  456.     mov    al,max_screen_line    ;fill the screen with this window.
  457.     mov    w1.lastline,al
  458.     mov    w1.lastpossible,al
  459.     mov    w1.firstcolumn,0
  460.     mov    ax,textseg
  461.     mov    w1.windseg,ax
  462.     call    paint_screen
  463.     ret
  464.  
  465.  
  466.     public    gotoxy
  467. gotoxy:
  468.     cmp    dl,max_screen_line    ;is max_screen_line ok?
  469.     jbe    gotoxy_1        ;yes.
  470.     mov    dl,max_screen_line    ;no - take min(dl, max_screen_line)
  471. gotoxy_1:
  472.     cmp    dh,num_screen_cols    ;are we on the screen?
  473.     jb    gotoxy_2
  474.     mov    dh,num_screen_cols    ;no - take min(dh, num_screen_cols-1)
  475.     dec    dh
  476. gotoxy_2:
  477.     mov    overwrite_rowcol,dx
  478.     call    position_cursor
  479.     ret
  480.  
  481.  
  482.     public    chrout
  483. chrout:
  484. ;enter with ax=char to "type" on screen.
  485. ;preserve si.
  486.     cmp    overwrite_flag,0    ;are we already overwriting?
  487.     jne    chrout_1        ;yes.
  488.     mov    overwrite_flag,1    ;say that we're overwriting
  489.     mov    window[0],TRASHED    ;trash the first line.
  490. chrout_1:
  491.     mov    dx,overwrite_rowcol    ;get the cursor position.
  492.     cmp    al,CR            ;go to left margin?
  493.     jne    chrout_4
  494.     mov    bh,0            ;trash the line because we're clearing it.
  495.     mov    bl,dl
  496.     mov    window[bx],TRASHED
  497.     call    clear_to_eol        ;yes - clear to end here.
  498.     mov    dh,0
  499.     jmp    chrout_exit
  500. chrout_4:
  501.     cmp    al,LF            ;go down a line?
  502.     jne    chrout_5
  503.     inc    dl
  504.     cmp    dl,max_screen_line    ;are we past the last line?
  505.     jbe    chrout_exit        ;no.
  506.     call    paint_screen        ;yes - paint the whole thing.
  507.     call    hardware_roll_up    ;yes - roll the screen up.
  508.     jnc    chrout_6
  509.     mov    dl,1            ;have to software scroll.
  510. chrout_7:
  511.     mov    al,dl
  512.     dec    al
  513.     call    move_line
  514.     inc    dl
  515.     cmp    dl,max_screen_line
  516.     jbe    chrout_7
  517. chrout_6:
  518.     mov    dl,max_screen_line    ;say on the last line.
  519.     push    dx            ;clear the entire line.
  520.     mov    dh,0
  521.     call    clear_to_eol
  522.     pop    dx
  523.     jmp    short chrout_exit
  524. chrout_5:
  525.     cmp    al,HT
  526.     jne    chrout_8
  527. chrout_9:
  528.     mov    ah,0
  529.     mov    al,' '
  530.     call    chrout_putch
  531.     test    dh,byte ptr tab_size
  532.     jnz    chrout_9
  533.     jmp    short chrout_exit
  534. chrout_8:
  535.     call    chrout_putch
  536. chrout_exit:
  537.     mov    overwrite_rowcol,dx    ;remember where we are.
  538.     call    position_cursor
  539.     ret
  540.  
  541.  
  542. chrout_putch:
  543.     mov    bh,0            ;trash the line.
  544.     mov    bl,dl
  545.     mov    window[bx],TRASHED
  546.     call    xychrout
  547.     inc    dh
  548.     ret
  549.  
  550.  
  551.     public    redisplay
  552. redisplay:
  553.  
  554.     mov    ax,textseg        ;is the current buffer showing in w1?
  555.     cmp    ax,w1.windseg
  556.     je    redisplay$_1        ;yes - all ok.
  557.  
  558.     xchg    w1.windseg,ax        ;no - put it in this window.
  559.     cmp    ax,w2.windseg        ;was the old w1 showing in w2?
  560.     jne    redisplay$_2        ;no - nothing special.
  561.  
  562.     push    ds
  563.     mov    ds,w2.windseg
  564.     mov    al,'*'            ;yes - make the split mark the point
  565.     call    goto_mark$
  566.     pop    ds
  567.  
  568. redisplay$_2:
  569.  
  570.     mov    bl,w1.firstline
  571.     mov    al,w1.lastline
  572.     call    trash_some_lines
  573.  
  574.     mov    ax,w1.windseg        ;is this buffer also in w2?
  575.     cmp    ax,w2.windseg
  576.     jne    redisplay$_1        ;no - no worries.
  577.  
  578.     mov    bl,w2.firstline        ;yes - trash one line so that
  579.     mov    bh,0            ;  the point is recomputed.  hack, hack.
  580.     mov    window[bx],TRASHED
  581.  
  582.     mov    ax,w2.pointrow        ;the place that the other window is at
  583.     mov    other_row,ax        ;  becomes the other row.
  584.  
  585.     mov    ax,'.'*256+'*'        ;set the split mark to the point.
  586.     call    set_mark
  587.  
  588. redisplay$_1:
  589.  
  590.     mov    overwrite_flag,0    ;no longer overwriting.
  591.     mov    dx,0            ;start in the upper left hand corner
  592.     mov    overwrite_rowcol,dx    ;  the next time we overwrite.
  593.   if 0
  594.     mov    dx,0*256+24        ;dh=column, dl=row.
  595.     mov    si,offset window
  596. rd_0:
  597.     lodsb
  598.     add    al,'A'
  599.     call    xychrout
  600.     inc    dh
  601.     cmp    dh,25
  602.     jb    rd_0
  603.     mov    si,offset inversed
  604. rd_1:
  605.     lodsb
  606.     add    al,'0'
  607.     call    xychrout
  608.     inc    dh
  609.     cmp    dh,48
  610.     jb    rd_1
  611.  
  612.   endif
  613.  
  614.     push    ds
  615.     mov    ds,w1.windseg
  616.     assume    ds:bufseg
  617.  
  618.     mov    si,topbot
  619.     mov    this_point,si
  620.  
  621.     mov    ax,next_redisp_line
  622.  
  623.     call    force_point_into_window
  624.     mov    ax,w1.pointrow
  625.     mov    this_row,ax
  626.  
  627.     call    redraw_trashed
  628.     call    write_scrollbar
  629.  
  630.     mov    ax,this_row
  631.     mov    w1.pointrow,ax
  632.  
  633.     pop    ds
  634.     assume    ds:data
  635.  
  636.     mov    dx,screen_column
  637.     sub    dx,w1.firstcolumn
  638.     mov    dh,dl
  639.     mov    dl,byte ptr w1.pointrow
  640.     call    position_cursor
  641.  
  642.     cmp    w2.windseg,0        ;is there a second window?
  643.     je    redisplay_one        ;no.
  644.     call    swap_windows
  645.     push    ds
  646.     mov    ax,w1.windseg        ;are they the same file?
  647.     cmp    ax,w2.windseg
  648.     mov    ds,ax            ;really w2.
  649.     assume    ds:bufseg
  650.     jne    redisplay__2
  651. ;two windows into the same buffer.
  652.     call    get_split_mark        ;get the split mark.
  653.     cmp    si,bottop        ;are we at the point?
  654.     jne    redisplay__1        ;no.
  655.     mov    si,topbot        ;yes - always use the top point.
  656. redisplay__1:
  657.     mov    this_point,si
  658.     mov    ax,other_row        ;get the row in the other window.
  659.     mov    this_row,ax
  660.     call    redraw_trashed
  661.     call    write_scrollbar
  662.     mov    ax,this_row
  663.     xchg    other_row,ax
  664.     sub    ax,other_row        ;how much did we adjust it by?
  665.     sub    w1.pointrow,ax        ;adjust pointrow, too.
  666.  
  667.     jmp    short redisplay__3
  668. redisplay__2:
  669. ;two windows, two buffers.
  670.     mov    si,topbot
  671.     mov    this_point,si
  672.     xor    ax,ax
  673.     call    force_point_into_window
  674.     mov    ax,w1.pointrow
  675.     mov    this_row,ax
  676.     call    redraw_trashed
  677.     call    write_scrollbar
  678.     mov    ax,this_row
  679.     mov    w1.pointrow,ax
  680. redisplay__3:
  681.     call    swap_windows
  682.     pop    ds
  683.     assume    ds:data
  684. redisplay_one:
  685.     mov    next_redisp_line,0    ;no more desired line
  686.     ret
  687.  
  688.  
  689. code    ends
  690.  
  691. code    segment    byte public
  692. ;all the code in this segment is entered with ds=bufseg, es=data
  693.     assume    cs:code, ds:bufseg, es:data
  694.  
  695.  
  696. write_scrollbar:
  697.     mov    ax,this_point
  698.     cmp    ax,topbot        ;is it in the lower half?
  699.     jbe    write_scrollbar_3    ;go if yes.
  700.     sub    ax,bottop        ;change this_point into a count of
  701.     add    ax,topbot        ;  characters before point.
  702. write_scrollbar_3:
  703.     sub    ax,toptop        ;now subtract off the beginning.
  704.     mov    dl,w1.lastline
  705.     sub    dl,w1.firstline
  706.     xor    dh,dh
  707.     mul    dx
  708.  
  709.     mov    cx,topbot
  710.     sub    cx,toptop
  711.     add    cx,botbot
  712.     sub    cx,bottop
  713.     inc    cx
  714.  
  715.     div    cx
  716.     add    al,w1.firstline
  717.     inc    al            ;remember, we aren't counting the first line.
  718.     mov    bl,al
  719.  
  720.     mov    dl,w1.firstline
  721.     mov    dh,num_screen_cols
  722.     mov    ax,8*256+UP_CHAR
  723.     call    xychrout
  724.  
  725.     inc    dl
  726. write_scrollbar_1:
  727.  
  728.     mov    ax,0b1h            ;50% halftone block
  729.     cmp    dl,bl            ;did we reach our cursor point yet?
  730.     jne    write_scrollbar_2
  731.     mov    ax,0dbh            ;solid block
  732. write_scrollbar_2:
  733.     call    xychrout
  734.  
  735.     inc    dl
  736.     cmp    dl,w1.lastline
  737.     jbe    write_scrollbar_1
  738.  
  739.     mov    ax,8*256+DOWN_CHAR
  740.     call    xychrout
  741.     ret
  742.  
  743.  
  744. set_window_percent:
  745. ;note that set_window_percent doesn't use ds.
  746. ;enter with si->window to set.
  747.     mov    cl,100
  748.     mov    ch,data:[si].lastline
  749.     sub    ch,data:[si].firstline
  750.     inc    ch
  751.     mov    al,toppercent
  752.     mul    ch
  753.     div    cl
  754.     cmp    al,ch
  755.     jb    set_window_percent_1
  756.     xor    al,al
  757. set_window_percent_1:
  758.     add    al,data:[si].firstline
  759.     mov    data:[si].firstpossible,al
  760.     mov    al,botpercent
  761.     mul    ch
  762.     div    cl
  763.     mov    ch,data:[si].lastline
  764.     sub    ch,al
  765.     jae    set_window_percent_2
  766.     mov    ch,data:[si].lastline
  767. set_window_percent_2:
  768.     mov    data:[si].lastpossible,ch
  769.     ret
  770.  
  771.  
  772. roll_window_down_2_j_1:
  773.     jmp    roll_window_down_2
  774. roll_window_down_5_j_1:
  775.     jmp    roll_window_down_5
  776.  
  777. roll_window_down:
  778. ;roll the window down until pointrow is in the window.
  779.  
  780.     mov    al,firstlimit
  781.     cbw
  782.     cmp    w1.pointrow,ax        ;if pointrow>=firstlimit, we don't
  783.     jge    roll_window_down_2_j_1    ;  need to roll down.
  784.  
  785. ;Are there any lines now on the screen that will remain?  Go if not.
  786.  
  787.     mov    cx,w1.pointrow
  788.     mov    bh,0
  789.     mov    bl,w1.lastline
  790.     add    cx,bx
  791.     mov    bl,w1.firstline
  792.     sub    cx,bx
  793.     mov    bl,firstlimit
  794.     cmp    cx,bx
  795.     jl    roll_window_down_5_j_1    ;we have to repaint the entire window.
  796.  
  797. ;Repaint screen if CGA, believe it or not, it is faster
  798.     call    read_ibm_cga
  799.     cmp    al,0
  800.     je    roll_window_down_normal
  801.     mov    cx,w1.pointrow
  802.     mov    bl,firstlimit
  803.     mov    bh,0
  804.     sub    cx,bx
  805.     inc    cx            ;Scroll if only one line
  806.     jnz    roll_window_down_5_j_1    ; it looks better
  807.  
  808. roll_window_down_normal:
  809.  
  810.     mov    dx,w1.pointrow
  811.     mov    cl,w1.firstline
  812.     mov    ch,0
  813.     sub    dx,cx
  814.     inc    dx
  815.  
  816. ;now compute the number of times we need to roll.
  817.  
  818.     mov    cx,w1.pointrow
  819.     sub    cx,bx
  820.     mov    w1.pointrow,bx        ;bx is firstlimit
  821.     neg    cx
  822.  
  823.   if 0
  824. ;Can we use the hardware scroll?  Go if not.
  825.  
  826.     cmp    w1.firstline,0
  827.     jne    roll_window_down_3
  828.     mov    al,max_screen_line
  829.     cmp    w1.lastline,al
  830.     jne    roll_window_down_3
  831.   endif
  832.  
  833. ;Use the hardware scroll unless there isn't one.
  834.  
  835.     xchg    cx,dx            ;get the distance to skip
  836.     call    skip_to_line
  837.     mov    cx,dx
  838.  
  839. roll_window_down_4:
  840.     mov    ah,w1.firstline
  841.     mov    al,w1.lastline
  842.     call    hardware_roll_down
  843.     jc    roll_window_down_3    ;can't hardware roll.
  844.  
  845. ;now adjust window[] for the change we just made to the screen.
  846.  
  847.     mov    bl,w1.firstline
  848.     mov    bh,0
  849.     mov    al,window[bx]        ;save the current values for later.
  850.     mov    ah,inversed[bx]
  851.     push    ax
  852.     push    si
  853.     call    redraw_compare        ;remember if we're inversing here.
  854.     mov    inversed[bx],al
  855.     call    redraw_line
  856.     call    remember_redrawn
  857.     pop    si
  858.     call    prevline
  859.     mov    window[bx],bl        ;remember that this line is real.
  860.     pop    ax            ;restore the old values.
  861. roll_window_down_6:
  862.     cmp    al,TRASHED        ;is this a trashed line?
  863.     je    roll_window_down_7
  864.     inc    al            ;no - say that the line's moved up.
  865.     cmp    al,max_screen_line    ;did it roll off the screen?
  866.     jbe    roll_window_down_7    ;no.
  867.     mov    al,TRASHED        ;yes - it's gone.
  868. roll_window_down_7:
  869.     inc    bl
  870.     xchg    al,window[bx]
  871.     xchg    ah,inversed[bx]
  872.     cmp    bl,w1.lastline
  873.     jb    roll_window_down_6
  874.     loop    roll_window_down_4
  875.     jmp    short roll_window_down_2
  876.  
  877. ;repaint screen.
  878.  
  879. roll_window_down_5:
  880.     call    center_this
  881.     jmp    short roll_window_down_2
  882.  
  883. ;Use software scroll.  All we do is roll the window array.
  884.  
  885. roll_window_down_3:
  886.     mov    bl,w1.firstline
  887.     mov    bh,0
  888.     mov    al,window[bx]        ;save the current value for later.
  889.     mov    ah,inversed[bx]
  890.     mov    window[bx],TRASHED
  891. roll_window_down_1:
  892.     inc    bl
  893.     xchg    al,window[bx]
  894.     xchg    ah,inversed[bx]
  895.     cmp    bl,w1.lastline
  896.     jb    roll_window_down_1
  897.     loop    roll_window_down_3
  898. roll_window_down_2:
  899.     ret
  900.  
  901.  
  902. roll_window_up_2_j_1:
  903.     jmp    roll_window_up_2
  904. roll_window_up_5_j_1:
  905.     jmp    roll_window_up_5
  906.  
  907. roll_window_up:
  908.  
  909.     mov    al,lastlimit
  910.     cbw
  911.     cmp    w1.pointrow,ax        ;if pointrow<=lastlimit, we don't
  912.     jle    roll_window_up_2_j_1    ;  need to roll up.
  913.  
  914. ;compute: pointrow-(lastline-firstline) > lastlimit
  915.  
  916. ;Are there any lines now on the screen that will remain?  Go if not.
  917.  
  918.     mov    cx,w1.pointrow
  919.     mov    bh,0
  920.     mov    bl,w1.firstline
  921.     add    cx,bx
  922.     mov    bl,w1.lastline
  923.     sub    cx,bx
  924.     mov    bl,lastlimit
  925.     cmp    cx,bx
  926.     jg    roll_window_up_5_j_1    ;we have to repaint the entire window.
  927.  
  928. ;Repaint screen if CGA, believe it or not, it is faster
  929.     call    read_ibm_cga
  930.     cmp    al,0
  931.     je    roll_window_up_normal
  932.     mov    cx,w1.pointrow
  933.     mov    bl,lastlimit
  934.     mov    bh,0
  935.     sub    cx,bx
  936.     dec    cx            ;Scroll if only one line
  937.     jnz    roll_window_up_5_j_1    ; it looks better
  938.  
  939. roll_window_up_normal:
  940.  
  941.     mov    dx,w1.pointrow
  942.     mov    cl,w1.lastline
  943.     mov    ch,0
  944.     sub    dx,cx
  945.     dec    dx
  946.  
  947. ;now compute the number of times we need to roll.
  948.  
  949.     mov    cx,w1.pointrow
  950.     sub    cx,bx
  951.     mov    w1.pointrow,bx        ;bx is lastlimit.
  952.  
  953. ;Can we use hardware scroll?  Go if not.
  954.  
  955.   if 0
  956.     cmp    w1.firstline,0
  957.     jne    roll_window_up_3
  958.     mov    al,max_screen_line
  959.     cmp    w1.lastline,al
  960.     jne    roll_window_up_3
  961.   endif
  962.  
  963. ;Use the hardware scroll unless there isn't one.
  964.  
  965.     xchg    cx,dx            ;get the distance to skip
  966.     call    skip_to_line
  967.     mov    cx,dx
  968.  
  969. roll_window_up_4:
  970.     mov    ah,w1.firstline
  971.     mov    al,w1.lastline
  972.     call    hardware_roll_up
  973.     jc    roll_window_up_3    ;can't hardware roll.
  974.  
  975. ;now adjust window[] for the change we just made to the screen.
  976.  
  977.     mov    bl,w1.lastline
  978.     mov    bh,0
  979.     mov    al,window[bx]        ;save the current values for later.
  980.     mov    ah,inversed[bx]
  981.     push    ax
  982.     call    redraw_compare        ;remember if we're inversing here.
  983.     mov    inversed[bx],al
  984.     call    redraw_line
  985.     call    remember_redrawn
  986.     mov    window[bx],bl        ;remember that this line is real.
  987.     pop    ax            ;restore old values.
  988. roll_window_up_6:
  989.     cmp    al,TRASHED        ;has this line been trashed?
  990.     je    roll_window_up_7
  991.     dec    al            ;no - say the line's been moved.
  992. roll_window_up_7:
  993.     dec    bl
  994.     xchg    al,window[bx]
  995.     xchg    ah,inversed[bx]
  996.     cmp    bl,w1.firstline
  997.     ja    roll_window_up_6
  998.     loop    roll_window_up_4
  999.     jmp    short roll_window_up_2
  1000.  
  1001. ;repaint screen.
  1002.  
  1003. roll_window_up_5:
  1004.     call    center_this
  1005.     jmp    short roll_window_up_2
  1006.  
  1007. ;Use software scroll.  All we do is roll the window array.
  1008.  
  1009. roll_window_up_3:
  1010.     mov    bl,w1.lastline
  1011.     mov    bh,0
  1012.     mov    al,window[bx]        ;save the current value for later.
  1013.     mov    ah,inversed[bx]
  1014.     mov    window[bx],TRASHED
  1015. roll_window_up_1:
  1016.     dec    bl
  1017.     xchg    al,window[bx]
  1018.     xchg    ah,inversed[bx]
  1019.     cmp    bl,w1.firstline
  1020.     ja    roll_window_up_1
  1021.     loop    roll_window_up_3
  1022. roll_window_up_2:
  1023.     ret
  1024.  
  1025.  
  1026. ;enter with pointrow=current relative screen line
  1027. ;exit with a line inserted before pointrow.
  1028.     public    window_insert
  1029. window_insert:
  1030.     push    si
  1031.     mov    ax,ds            ;is this in window 1?
  1032.     cmp    ax,w1.windseg
  1033.     jne    window_insert_1
  1034.     mov    si,offset w1
  1035.     call    window_ins
  1036. window_insert_1:
  1037.     mov    ax,ds            ;is this in window 2?
  1038.     cmp    ax,w2.windseg
  1039.     jne    window_insert_2
  1040.     mov    si,offset w2
  1041.     call    window_ins
  1042. window_insert_2:
  1043.     mov    ax,ds            ;are we showing in both windows?
  1044.     cmp    ax,w1.windseg
  1045.     jne    window_insert_3
  1046.     cmp    ax,w2.windseg
  1047.     jne    window_insert_3
  1048.     call    split_at_point        ;is the split mark at or after the point?
  1049.     jnc    window_insert_3        ;no
  1050.     inc    other_row        ;yes - must increment the other row.
  1051. window_insert_3:
  1052.     pop    si
  1053.     ret
  1054.  
  1055. ;private subroutine, called by window_insert to insert a line in a window.
  1056. ;enter with si-> a window structure.
  1057. window_ins:
  1058.     mov    bx,data:[si].pointrow
  1059.     mov    al,data:[si].firstline
  1060.     cbw
  1061.     cmp    bx,ax            ;are we above the screen?
  1062.     jl    window_ins_3        ;yes - exit.
  1063.     mov    al,data:[si].lastline
  1064.     cmp    bx,ax            ;are we below the screen?
  1065.     jg    window_ins_2        ;yes - go down a row.
  1066.  
  1067.     mov    window[bx],TRASHED
  1068.     mov    al,TRASHED
  1069.     jmp    short window_ins_4
  1070. window_ins_1:
  1071.     xchg    al,window[bx]
  1072.     xchg    ah,inversed[bx]
  1073. window_ins_4:
  1074.     inc    bl
  1075.     cmp    bl,data:[si].lastline
  1076.     jbe    window_ins_1
  1077. window_ins_2:
  1078.     inc    data:[si].pointrow
  1079. window_ins_3:
  1080.     ret
  1081.  
  1082.  
  1083. ;enter with pointrow=current relative screen line
  1084. ;exit with the line at pointrow deleted.
  1085.     public    window_delete
  1086. window_delete:
  1087.     push    si
  1088.     mov    ax,ds            ;is this in window 1?
  1089.     cmp    ax,w1.windseg
  1090.     jne    window_delete_1
  1091.     mov    si,offset w1
  1092.     call    window_del
  1093. window_delete_1:
  1094.     mov    ax,ds            ;is this in window 2?
  1095.     cmp    ax,w2.windseg
  1096.     jne    window_delete_2
  1097.     mov    si,offset w2
  1098.     call    window_del
  1099. window_delete_2:
  1100.     mov    ax,ds            ;are we showing in both windows?
  1101.     cmp    ax,w1.windseg
  1102.     jne    window_delete_3
  1103.     cmp    ax,w2.windseg
  1104.     jne    window_delete_3
  1105.     call    split_at_point        ;is the split mark at or after the point?
  1106.     jnc    window_delete_3        ;no
  1107.     dec    other_row        ;yes - must decrement the other row.
  1108. window_delete_3:
  1109.     pop    si
  1110.     ret
  1111.  
  1112. ;private subroutine, called by window_delete to delete a line from a window.
  1113. ;enter with si-> a window structure.
  1114. window_del:
  1115.     mov    bx,data:[si].pointrow
  1116.     mov    al,data:[si].firstline
  1117.     cbw
  1118.     cmp    bx,ax            ;are we above the screen?
  1119.     jl    window_del_4        ;yes.
  1120.     mov    al,data:[si].lastline
  1121.     cbw
  1122.     cmp    bx,ax            ;are we below the screen?
  1123.     jg    window_del_1        ;yes.
  1124.  
  1125.     mov    window[bx],TRASHED    ;kill the line the cursor is on.
  1126.     jmp    short window_del_5    ;go into while...do loop
  1127. window_del_4:
  1128.     inc    data:[si].pointrow
  1129.     jmp    short window_del_1
  1130. window_del_3:
  1131.     mov    al,window[bx+1]
  1132.     mov    ah,inversed[bx+1]
  1133.     mov    window[bx],al
  1134.     mov    inversed[bx],ah
  1135. window_del_5:
  1136.     inc    bl
  1137.     cmp    bl,data:[si].lastline
  1138.     jb    window_del_3
  1139.     mov    window[bx],TRASHED    ;kill lastline
  1140. window_del_1:
  1141.     ret
  1142.  
  1143.  
  1144.     public    trash_line
  1145. trash_line:
  1146. ;destroy the line that the point is on if it's also in the window.
  1147.     mov    ax,ds            ;is this in window 1?
  1148.     cmp    ax,w1.windseg
  1149.     jne    trash_line_1
  1150.     mov    si,offset w1
  1151.     call    trash_line_0
  1152. trash_line_1:
  1153.     mov    ax,ds            ;is this in window 2?
  1154.     cmp    ax,w2.windseg
  1155.     jne    trash_line_2
  1156.     mov    si,offset w2
  1157.     call    trash_line_0
  1158. trash_line_2:
  1159.     ret
  1160.  
  1161.  
  1162. ;enter with si-> a window structure.
  1163. trash_line_0:
  1164.     mov    bx,data:[si].pointrow
  1165.     mov    al,data:[si].firstline
  1166.     cbw
  1167.     cmp    bx,ax
  1168.     jl    trash_line_3
  1169.     mov    al,data:[si].lastline
  1170.     cbw
  1171.     cmp    bx,ax
  1172.     jg    trash_line_3
  1173.     mov    window[bx],TRASHED
  1174. trash_line_3:
  1175.     ret
  1176.  
  1177.  
  1178.     public    up_lines
  1179. up_lines:
  1180.     mov    ax,ds            ;is this in window 2?
  1181.     cmp    ax,w1.windseg
  1182.     jne    up_lines_1
  1183.     sub    w1.pointrow,bx
  1184. up_lines_1:
  1185.     mov    ax,ds            ;is this in window 2?
  1186.     cmp    ax,w2.windseg
  1187.     jne    up_lines_2
  1188.     sub    w2.pointrow,bx
  1189. up_lines_2:
  1190.     ret
  1191.  
  1192.  
  1193.     public    down_lines
  1194. down_lines:
  1195.     mov    ax,ds            ;is this in window 1?
  1196.     cmp    ax,w1.windseg
  1197.     jne    down_lines_1
  1198.     add    w1.pointrow,bx
  1199. down_lines_1:
  1200.     mov    ax,ds            ;is this in window 2?
  1201.     cmp    ax,w2.windseg
  1202.     jne    down_lines_2
  1203.     add    w2.pointrow,bx
  1204. down_lines_2:
  1205.     ret
  1206.  
  1207.  
  1208.     public    paint_screen
  1209. paint_screen:
  1210. ;note that paint doesn't use ds.
  1211. ;what's on the screen is garbage.
  1212. ;preserve si, dx.
  1213.     mov    bl,0
  1214.     mov    al,max_screen_line
  1215.     call    trash_some_lines
  1216.     ret
  1217.  
  1218.  
  1219. center_window:
  1220. ;note that center doesn't use ds.
  1221. ;preserve dx.
  1222. center_this:
  1223.     mov    cl,w1.lastline        ;compute the middle of the screen.
  1224.     sub    cl,w1.firstline
  1225.     sar    cl,1
  1226.     add    cl,w1.firstline
  1227.     mov    ch,0
  1228.     mov    w1.pointrow,cx
  1229.     mov    bl,w1.firstline
  1230.     mov    al,w1.lastline
  1231.     call    trash_some_lines
  1232.     ret
  1233.  
  1234.  
  1235.     public    paint_window
  1236. paint_window:
  1237. ;preserve dx.
  1238.     mov    ax,textseg
  1239.     cmp    ax,w1.windseg
  1240.     jne    paint_window_1
  1241.     mov    bl,w1.firstline
  1242.     mov    al,w1.lastline
  1243.     call    trash_some_lines
  1244. paint_window_1:
  1245.     mov    ax,textseg
  1246.     cmp    ax,w2.windseg
  1247.     jne    paint_window_2
  1248.     mov    bl,w2.firstline
  1249.     mov    al,w2.lastline
  1250.     call    trash_some_lines
  1251. paint_window_2:
  1252.     ret
  1253.  
  1254.  
  1255. trash_some_lines:
  1256. ;enter with bl=first line to destroy, al=last line.
  1257. ;preserve si, dx.
  1258.     mov    w1.firstcolumn,0    ;go to the first column.
  1259.     mov    bh,0
  1260. trash_some_lines_0:
  1261.     mov    window[bx],TRASHED
  1262.     inc    bl
  1263.     cmp    bl,al
  1264.     jbe    trash_some_lines_0
  1265.     mov    al,w1.firstpossible    ;ensure that we're not above the screen.
  1266.     cbw
  1267.     cmp    w1.pointrow,ax
  1268.     jge    trash_some_lines_1    ;we're not.
  1269.     mov    w1.pointrow,ax
  1270. trash_some_lines_1:
  1271.     mov    al,w1.lastpossible    ;ensure that we're not below the screen.
  1272.     cbw
  1273.     cmp    w1.pointrow,ax
  1274.     jle    trash_some_lines_2    ;we're not.
  1275.     mov    w1.pointrow,ax
  1276. trash_some_lines_2:
  1277.     ret
  1278.  
  1279.  
  1280. ;swap the two window data structures.
  1281. swap_windows:
  1282.     mov    si,offset w1
  1283.     mov    di,offset w2
  1284.     mov    cx,(size wind_struc)
  1285. swap_windows_0:
  1286.     mov    al,data:[si]
  1287.     xchg    al,data:[di]
  1288.     mov    data:[si],al
  1289.     inc    si
  1290.     inc    di
  1291.     loop    swap_windows_0
  1292.     ret
  1293.  
  1294.  
  1295. force_point_into_window:
  1296. ;enter with al=the desired row, =0 if we don't care.
  1297. comment /**********************************************************************
  1298. * roll the window array until pointrow is on the screen.
  1299. * when we roll the array, the lines we roll in must be repainted.
  1300. * for example, assume: screen is 0..23
  1301. * if pointrow is     5, then we're done.
  1302. * if pointrow is    -7, then we must roll down 7 lines.
  1303. * if pointrow is <=-24, then we must roll down 24 lines, which says that the
  1304. *                     entire screen will be repainted.
  1305. * if pointrow is    27, then we must roll up 3 lines.
  1306. * if pointrow is  >=48, then we must roll up 24 lines, which says that the
  1307. *                  entire screen will be repainted.
  1308. *****************************************************************************/
  1309.     mov    bl,w1.firstpossible
  1310.     mov    bh,w1.lastpossible
  1311.     or    al,al            ;do we have a desired row?
  1312.     je    redisplay_1        ;no.
  1313.     dec    al
  1314.     cmp    al,bl            ;above firstpossible?
  1315.     ja    redisplay_0        ;yes - ok.
  1316.     mov    al,bl            ;no - clip to firstpossible.
  1317. redisplay_0:
  1318.     cmp    al,bh            ;below lastpossible?
  1319.     jb    redisplay_00        ;yes - ok.
  1320.     mov    al,bh            ;no - clip to lastpossible.
  1321. redisplay_00:
  1322.     mov    bl,al
  1323.     mov    bh,al
  1324. redisplay_1:
  1325.     mov    firstlastlimits,bx
  1326. ;now truncate firstlimit if we can't get there.
  1327.     mov    al,firstlimit
  1328.     cbw                ;compute the number of display lines
  1329.     sub    al,w1.firstline        ;  desired before the cursor line.
  1330.     cmp    ax,linesbefore        ;is it even possible to get there?
  1331.     jb    redisplay_2        ;yes - just do it.
  1332.     mov    ax,linesbefore        ;no - truncate firstlimit to
  1333.     add    al,w1.firstline        ;  the largest possible.
  1334.     mov    firstlimit,al
  1335. redisplay_2:
  1336.  
  1337. ;Now update row,col
  1338.  
  1339.     call    compute_cursor$
  1340.     mov    screen_column,dx
  1341.     sub    dx,w1.firstcolumn    ;are we to the left of the screen?
  1342.     jb    redisplay_01        ;yes - must roll the screen right.
  1343.     cmp    dx,word ptr num_screen_cols    ;are we on the screen?
  1344.     jb    redisplay_02        ;yes - we don't have the roll left.
  1345.  
  1346. ;roll the window to the left.
  1347.  
  1348. comment /
  1349. Eventually, we'll be smart about all this and really scroll the screen.
  1350. For now, we'll repaint the screen every time we roll.
  1351.     jmp    short redisplay_02
  1352. /
  1353.  
  1354. redisplay_01:
  1355.  
  1356. ;roll the window to the right.
  1357.  
  1358. comment /
  1359. Eventually, we'll be smart about all this and really scroll the screen.
  1360. For now, we'll repaint the screen every time we roll.
  1361. /
  1362.  
  1363.     add    dx,w1.firstcolumn    ;restore the cursor position.
  1364.     mov    bl,w1.firstline
  1365.     mov    al,w1.lastline
  1366.     call    trash_some_lines
  1367.     mov    ax,word ptr num_screen_cols
  1368.     shr    ax,1
  1369.     sub    dx,ax            ;put the cursor in middle of screen.
  1370.     jae    redisplay_03
  1371.     mov    dx,0            ;column is less than 40.
  1372. redisplay_03:
  1373.     and    dl,not 7        ;back up to previous tab stop.
  1374.     mov    w1.firstcolumn,dx    ;that is where we start redisplaying.......................
  1375. redisplay_02:
  1376.  
  1377. ;now roll the screen up or down, as needed.
  1378.  
  1379.     call    roll_window_down
  1380.     call    roll_window_up
  1381.     ret
  1382.  
  1383.  
  1384. redraw_trashed:
  1385. ;redraw all changed lines if there are any to redraw.
  1386. redraw_trashed_4:
  1387.     mov    bl,w1.firstline
  1388.     mov    bh,0
  1389.     mov    dh,0            ;initially, we don't need to redraw any.
  1390. redraw_trashed_3:
  1391.     mov    dl,window[bx]        ;get new window contents.
  1392.     or    dh,dl            ;remember if we need to redraw any.
  1393.     or    dl,dl            ;if positive, it's a line to be moved.
  1394.     js    redraw_trashed_5        ;if negative, skip it.
  1395.     cmp    dl,bl            ;is the line already there?
  1396.     je    redraw_trashed_5        ;yes - skip it.
  1397.     mov    di,offset window    ;is this row referred to?
  1398.     mov    cl,max_screen_line
  1399.     inc    cl
  1400.     mov    ch,0
  1401.     mov    al,bl
  1402.     repne    scasb            ;scan for the row.
  1403.     je    redraw_trashed_5        ;yes - we can't move something here.
  1404.     call    move_line        ;move dl to al.
  1405.     mov    dh,0            ;get the source line.
  1406.     mov    di,dx
  1407.     mov    al,inversed[di]        ;transfer the inversed contents.
  1408.     mov    inversed[bx],al
  1409.     mov    window[bx],bl        ;say that this line is where it is.
  1410.     jmp    redraw_trashed_4        ;restart search.
  1411. redraw_trashed_5:
  1412.     inc    bl
  1413.     cmp    bl,w1.lastline
  1414.     jbe    redraw_trashed_3
  1415.  
  1416.     cmp    inverse_flag,0        ;if we're inversing, we might need to redraw.
  1417.     jne    redraw_trashed_1
  1418.     or    dh,dh            ;do we need to redraw any lines?
  1419.     jns    redraw_trashed_9        ;no.
  1420.  
  1421. redraw_trashed_1:
  1422.     mov    bl,w1.firstline
  1423.     mov    bh,0
  1424.     mov    cx,this_row        ;get the row that the point is on.
  1425.     sub    cx,bx
  1426.     call    skip_to_line        ;find the first line on the screen.
  1427.     call    redraw_anyway        ;see if we need to redraw anyway.
  1428. redraw_trashed_7:
  1429.     call    redraw_compare        ;remember if we're inversing here.
  1430.     mov    inversed[bx],al
  1431.     cmp    window[bx],0
  1432.     jns    redraw_trashed_a        ;if negative, redraw it.
  1433.     call    redraw_line
  1434.     mov    window[bx],bl        ;remember that this line is drawn.
  1435. redraw_trashed_a:
  1436.     call    remember_redrawn
  1437.     inc    bl
  1438.     cmp    bl,w1.lastline
  1439.     jbe    redraw_trashed_7
  1440. redraw_trashed_9:
  1441.     mov    inversing,0        ;say that we're not inversing.
  1442.     ret
  1443.  
  1444.  
  1445. remember_redrawn:
  1446. ;enter with si->text, bx=screen line.
  1447. ;exit with si->next line.
  1448.     call    nextline
  1449.     shl    inversed[bx],1
  1450.     shl    inversed[bx],1
  1451.     call    redraw_compare
  1452.     or    inversed[bx],al
  1453.     ret
  1454.  
  1455.  
  1456. redraw_anyway:
  1457. ;preserve si,bx.
  1458.     cmp    inverse_flag,0
  1459.     je    redraw_anyway_1
  1460.     push    si
  1461.     push    bx
  1462. redraw_anyway_2:
  1463.     call    redraw_compare
  1464.     push    ax
  1465.     call    nextline        ;see if this line contains the mark or point.
  1466.     call    redraw_compare
  1467.     pop    cx
  1468.     mov    ch,cl            ;save a copy.
  1469.     xor    cl,al            ;see if the bits changed.
  1470.     test    cl,1            ;is the point in this line?
  1471.     jne    redraw_anyway_yes    ;yes - must redraw.
  1472.     shl    ch,1
  1473.     shl    ch,1
  1474.     or    al,ch            ;make up the compare byte.
  1475.     cmp    al,inversed[bx]        ;have they changed?
  1476.     je    redraw_anyway_no    ;no - don't necessarily redraw.
  1477. redraw_anyway_yes:
  1478.     mov    window[bx],TRASHED    ;say that this line is gone.
  1479. redraw_anyway_no:
  1480.     inc    bl
  1481.     cmp    bl,w1.lastline
  1482.     jbe    redraw_anyway_2
  1483.     pop    bx
  1484.     pop    si
  1485. redraw_anyway_1:
  1486.     ret
  1487.  
  1488.  
  1489. redraw_compare:
  1490. ;enter with si->text buffer.
  1491. ;exit with al and 1 = 1 if si<point,
  1492. ;          al and 2 = 2 if si<mark.
  1493.     cmp    si,inverse_mark        ;set cy if si is below inverse_mark (mark)
  1494.     rcl    al,1
  1495.     cmp    si,bottop        ;set cy if si is below bottop (point)
  1496.     rcl    al,1
  1497.     and    al,3            ;get rid of other bits.
  1498.     ret
  1499.  
  1500.  
  1501.  
  1502. skip_to_line:
  1503. ;enter with cx=number of lines to move forward or backward.
  1504. ;Note: positive values move toward top of file.
  1505. ;return si -> beginning of desired line.
  1506. ;don't destroy dx.
  1507.     mov    si,this_point        ;get the point.
  1508.     or    cx,cx            ;is cx negative?
  1509.     js    skip_to_line_4        ;yes - we have to move forward.
  1510.     cmp    [si-2].w,LINENEW    ;if we're not at the beginning of
  1511.     je    skip_to_line_3        ;  this line, backup to beginning.
  1512.     call    prevline
  1513. skip_to_line_3:
  1514.     jcxz    skip_to_line_2
  1515. skip_to_line_1:
  1516.     call    prevline
  1517.     loopne    skip_to_line_1
  1518.     jne    skip_to_line_2        ;did we hit the beginning?
  1519.     inc    cx            ;yes - restore the count.
  1520.     sub    this_row,cx        ;adjust this row.
  1521.     jmp    short skip_to_line_2
  1522. skip_to_line_4:
  1523.     neg    cx            ;make cx into a positive count.
  1524.                     ;cx is at least one.
  1525. skip_to_line_5:
  1526.     call    nextline
  1527.     loopne    skip_to_line_5
  1528. skip_to_line_2:
  1529.     mov    al,inverse_flag        ;are we inversing?
  1530.     cmp    al,0
  1531.     je    skip_to_line_6        ;no.
  1532.     push    bx
  1533.     push    dx
  1534.     push    si
  1535.     call    get_mark        ;the mark is in inverse_flag
  1536.     mov    inverse_mark,si        ;remember where the inverse mark is.
  1537.     pop    si
  1538.     pop    dx
  1539.     pop    bx
  1540. skip_to_line_6:
  1541.     ret
  1542.  
  1543.  
  1544. redraw_line:
  1545. ;enter with si -> line to be redrawn, bl=row of line.
  1546. ;paint from firstcolumn for num_screen_cols columns.
  1547. ;this routine is intense.
  1548. ;preserve cx, bx
  1549.     call    redraw_set
  1550.     mov    di,0            ;start at column zero.
  1551.     mov    dh,0
  1552.     mov    dl,bl
  1553.     mov    bl,-1            ;start without trailing blanks.
  1554.     cmp    si,botbot        ;are we at bottom already?
  1555.     je    redraw_line_9_j_1    ;yes - clear to eol.
  1556. redraw_line_2:
  1557.     call    redraw_pointer
  1558.     cmp    si,botbot        ;are we at bottom already?
  1559.     je    redraw_line_3        ;yes - exit.
  1560.     mov    ax,[si]
  1561.     cmp    ax,LINENEW        ;done with line?
  1562.     je    redraw_line_3        ;yes - exit.
  1563.     inc    si
  1564.     cmp    dh,num_screen_cols    ;at right hand column?
  1565.     jae    redraw_line_d        ;yes - don't print.
  1566.     cmp    di,w1.firstcolumn    ;before first column?
  1567.     jb    redraw_line_4        ;yes - just compute new column.
  1568.     cmp    al,' '            ;possible trailing blanks.
  1569.     je    redraw_line_a
  1570.     cmp    al,HT
  1571.     jne    redraw_line_b        ;not trailing blanks - forget.
  1572. redraw_line_a:
  1573.     cmp    bl,-1            ;are we already remembering?
  1574.     jne    redraw_line_c        ;yes - don't remember again.
  1575.     mov    bl,dh            ;found a trailing blank character,
  1576.     mov    bp,si            ;  remember where it was.
  1577.     jmp    short redraw_line_c
  1578. redraw_line_b:
  1579.     mov    bl,-1            ;printable char - forget trailing blanks.
  1580. redraw_line_c:
  1581.     call    xy_char_put
  1582.     jmp    redraw_line_2
  1583. redraw_line_d:
  1584.     cmp    dh,num_screen_cols    ;did we just get there?
  1585.     ja    redraw_line_2        ;no.
  1586.     dec    dh
  1587.     mov    ax,8*256+MORE_CHAR    ;yes - print the "more" symbol.
  1588.     call    xychrout
  1589.     mov    dh,num_screen_cols    ;say that we're in the next column.
  1590.     inc    dh
  1591.     jmp    redraw_line_2
  1592. redraw_line_4:
  1593.     inc    di
  1594.     cmp    al,HT            ;only tabs are special
  1595.     jne    redraw_line_2
  1596.     mov    ax,di
  1597.     add    ax,tab_size        ;round up to next tab stop.
  1598.     or    ax,tab_size        ;same as 'and not'.
  1599.     xor    ax,tab_size
  1600.     mov    di,ax
  1601.     jmp    redraw_line_2
  1602. redraw_line_9_j_1:
  1603.     jmp    redraw_line_9
  1604. redraw_line_3:
  1605.     cmp    showblanks,0        ;should we show blanks?
  1606.     je    redraw_line_8
  1607.     cmp    bl,-1            ;are there any trailing blanks?
  1608.     je    redraw_line_8        ;no.
  1609.     mov    dh,bl            ;restore the column.
  1610.     xchg    si,bp            ;save the current and restore the old.
  1611.     dec    si
  1612.     call    redraw_set
  1613. redraw_line_7:
  1614.     call    redraw_pointer
  1615.     cmp    si,botbot        ;hit the bottom yet?
  1616.     je    redraw_line_e        ;yes - we're done.
  1617.     mov    ax,[si]            ;get the next char.
  1618.     cmp    ax,LINENEW
  1619.     je    redraw_line_e
  1620.     cmp    dh,num_screen_cols
  1621.     jae    redraw_line_f
  1622.     inc    si
  1623.     cmp    al,' '            ;it can only be a tab or a space.
  1624.     je    redraw_line_6        ;must be a space.
  1625. redraw_line_5:
  1626.     cmp    dh,num_screen_cols
  1627.     jae    redraw_line_f
  1628.     mov    ax,8*256+TRAIL_TAB    ;output a trailing tab char.
  1629.     call    xychrout
  1630.     inc    dh
  1631.     test    dh,byte ptr tab_size    ;at a tab stop yet?
  1632.     jne    redraw_line_5        ;no.
  1633.     jmp    redraw_line_7
  1634. redraw_line_6:                ;output a trailing blank char.
  1635.     mov    ax,8*256+TRAIL_BLANK
  1636.     call    xychrout
  1637.     inc    dh
  1638.     jmp    redraw_line_7
  1639. redraw_line_f:
  1640.     dec    dh
  1641.     mov    ax,8*256+MORE_CHAR    ;yes - print the "more" symbol.
  1642.     call    xychrout
  1643.     inc    dh
  1644. redraw_line_e:
  1645.     mov    si,bp            ;restore the text pointer.
  1646. redraw_line_8:
  1647.     cmp    dh,num_screen_cols    ;put a newline symbol if there's room.
  1648.     jae    redraw_line_9
  1649.     cmp    inversing,0        ;only if we're inversing.
  1650.     je    redraw_line_9
  1651.     mov    ax,8*256+NEWLINE_CHAR    ;newline symbol.
  1652.     call    xychrout
  1653.     inc    dh
  1654. redraw_line_9:
  1655.     call    clear_to_eol
  1656.     mov    bh,0            ;restore bx.
  1657.     mov    bl,dl
  1658.     ret
  1659.  
  1660.  
  1661. redraw_pointer:
  1662. ;adjust si from the top to the bottom if necessary, and adjust inversing.
  1663.     cmp    si,topbot        ;at the point yet?
  1664.     jne    redraw_pointer_1    ;no.
  1665.     mov    si,bottop
  1666.     cmp    inverse_flag,0        ;are we inversing?
  1667.     je    redraw_pointer_1    ;no.
  1668.     mov    ax,ds
  1669.     cmp    ax,inverse_seg        ;is this our segment?
  1670.     jne    redraw_pointer_1    ;no.
  1671.     not    inversing        ;say that we've passed the point.
  1672. redraw_pointer_1:
  1673.     cmp    si,inverse_mark        ;are we at the inverse mark?
  1674.     jne    redraw_pointer_2    ;yes - maybe inverse.
  1675.     cmp    inverse_flag,0        ;are we inversing?
  1676.     je    redraw_pointer_2    ;no.
  1677.     mov    ax,ds
  1678.     cmp    ax,inverse_seg        ;is this our segment?
  1679.     jne    redraw_pointer_2    ;no.
  1680.     not    inversing        ;say that we've passed the point.
  1681. redraw_pointer_2:
  1682.     ret
  1683.  
  1684.  
  1685. redraw_set:
  1686.     cmp    si,topbot        ;have we hit the top bottm yet?
  1687.     jne    redraw_set_3
  1688.     mov    si,bottop
  1689. redraw_set_3:
  1690.     cmp    inverse_flag,0        ;if we're not inversing, don't inverse.
  1691.     je    redraw_set_1
  1692.     mov    ax,ds
  1693.     cmp    ax,inverse_seg        ;is this our segment?
  1694.     jne    redraw_set_1        ;no.
  1695.     call    redraw_compare
  1696.     cmp    si,inverse_mark        ;are we exactly at the mark?
  1697.     jne    redraw_set_2        ;no - just check parity.
  1698.     xor    al,2            ;yes - flip the associated bit.
  1699. redraw_set_2:
  1700.     mov    inversing,0        ;say that we're not inversing.
  1701.     or    al,al            ;look for 00,11 or 10,01
  1702.     jpe    redraw_set_1        ;go if not within point and mark.
  1703.     not    inversing        ;say that we're inversing.
  1704. redraw_set_1:
  1705.     ret
  1706.  
  1707.  
  1708. xy_char_put:
  1709. ;put a char on the screen.  Interpret tabs.
  1710.     cmp    al,HT
  1711.     jne    xy_char_put_1
  1712. xy_char_put_2:
  1713.     mov    ax,8*256+TAB_BLANK    ;output a tab blank char.
  1714.     call    xychrout
  1715.     inc    dh
  1716.     test    dh,byte ptr tab_size
  1717.     jnz    xy_char_put_2
  1718.     ret
  1719. xy_char_put_1:
  1720.     mov    ah,0
  1721.     call    xychrout
  1722.     inc    dh
  1723. xy_char_put_4:
  1724.     ret
  1725.  
  1726.  
  1727.     public    prevline
  1728. prevline:
  1729. ;retreat si to the previous line.
  1730. ;return zr if si->beginning of file (and leave si alone)
  1731. ;return nz otherwise.
  1732.  
  1733. ;are we at the beginning of the file already?
  1734.     cmp    si,toptop
  1735.     je    prevline_beginning    ;yes - exit.
  1736.  
  1737. ;where are we in the file?
  1738.     cmp    si,topbot        ;at, before or after the point?
  1739.     jbe    prevline_before
  1740. prevline_after:
  1741.     dec    si
  1742.     cmp    si,bottop        ;have we reached the top of the bottom?
  1743.     je    prevline_at        ;yes - drop down to prevline_before.
  1744.     cmp    [si-2].w,LINENEW    ;at the beginning of a new line?
  1745.     jne    prevline_after        ;no - keep looking.
  1746.     dec    si            ;did we just find a non-real newline?
  1747.     cmp    si,bottop        ;if we did, then si is now at bottop
  1748.     je    prevline_at        ;  and we need to keep searching.
  1749.     inc    si            ;restore si and exit.
  1750.     jmp    short prevline_exit
  1751.  
  1752. prevline_at:
  1753.     mov    si,topbot        ;start searching at the bottom
  1754.     inc    si            ;  of the top.
  1755. prevline_before:
  1756.     dec    si
  1757.     cmp    [si-2].w,LINENEW    ;at the beginning of a new line?
  1758.     jne    prevline_before        ;no - keep looking.
  1759. prevline_exit:
  1760.     or    si,si            ;return nz
  1761. prevline_beginning:
  1762.     ret
  1763.  
  1764.  
  1765.     public    nextline
  1766. nextline:
  1767. ;advance si to the next line.
  1768. ;return zr if si->end of file (and leave si alone)
  1769. ;return nz otherwise.
  1770.     cmp    si,topbot
  1771.     jne    nextline_1
  1772.     mov    si,bottop
  1773. nextline_1:
  1774.     cmp    si,botbot
  1775.     je    nextline_2
  1776.     cmp    [si].w,LINENEW
  1777.     je    nextline_3
  1778.     inc    si
  1779.     jmp    nextline
  1780. nextline_3:
  1781.     add    si,2
  1782.     or    si,si
  1783.     ret
  1784. nextline_2:
  1785.     push    ax
  1786.     xor    ax,ax
  1787.     pop    ax
  1788.     ret
  1789.  
  1790.  
  1791.     public    compute_one
  1792. compute_one:
  1793.     cmp    al,HT
  1794.     jne    compute_one_1
  1795.     or    dl,byte ptr tab_size    ;same as 'and not'
  1796.     xor    dl,byte ptr tab_size
  1797.     add    dx,tab_size
  1798. compute_one_1:
  1799.     inc    dx
  1800.     ret
  1801.  
  1802.  
  1803. code    ends
  1804.  
  1805.     end
  1806.